#region Using

using System;
using System.Xml;
using System.IO;
using System.Globalization;
using System.Collections.Generic;
using System.Collections.Specialized;
using BlogEngine.Core;
using BlogEngine.Core.Provider.Interfaces;

#endregion

namespace BlogEngine.Core.Provider.XML
{
	/// <summary>
	/// A storage provider for BlogEngine that uses XML files.
	/// <remarks>
	/// To build another provider, you can just copy and modify
	/// this one. Then add it to the web.config's BlogEngine section.
	/// </remarks>
	/// </summary>
	public class CICategories : ICategories
	{


		/// <summary>
		/// Gets a Category based on a Guid
		/// </summary>
		/// <param name="id">The category's Guid.</param>
		/// <returns>A matching Category</returns>
		public Category Select(Guid id)
		{
			Category category = new Category();

			foreach (Category cat in Category.Items)
			{
				if (cat.Id == id)
					category = cat;
			}
			category.MarkOld();
			return category;
		}

		/// <summary>
		/// Inserts a Category
		/// </summary>
		/// <param name="category">Must be a valid Category object.</param>
		public void Insert(Category category)
		{
			List<Category> categories = Category.Items;
			categories.Add(category);
			categories.Sort();

			RewriteCategoryFile(categories);
		}

		/// <summary>
		/// Updates a Category
		/// </summary>
		/// <param name="category">Must be a valid Category object.</param>
		public void Update(Category category)
		{
			List<Category> categories = Category.Items;

			if (categories.Contains(category))
				categories.Remove(category);

			categories.Add(category);
			categories.Sort();

			RewriteCategoryFile(categories);
		}

		/// <summary>
		/// Deletes a Category
		/// </summary>
		/// <param name="category">Must be a valid Category object.</param>
		public void Delete(Category category)
		{
			List<Category> categories = Category.Items;

			if (categories.Contains(category))
				categories.Remove(category);

			RewriteCategoryFile(categories);
		}

		private void RewriteCategoryFile(List<Category> categories)
		{
			string fileName = Provider.Folder + "categories.xml";

			if (File.Exists(fileName))
				File.Delete(fileName);

			using (XmlTextWriter writer = new XmlTextWriter(fileName, System.Text.Encoding.UTF8))
			{
				writer.Formatting = Formatting.Indented;
				writer.Indentation = 4;
				writer.WriteStartDocument(true);
				writer.WriteStartElement("categories");

				foreach (Category cat in categories)
				{
					writer.WriteStartElement("category");
					writer.WriteAttributeString("id", cat.Id.ToString());
					writer.WriteAttributeString("description", cat.Description);
					writer.WriteAttributeString("slug", cat.Slug);
					writer.WriteAttributeString("parent", cat.Parent.ToString());
					writer.WriteAttributeString("order", cat.Order.ToString());
					writer.WriteValue(cat.Title);
					writer.WriteEndElement();
					cat.MarkOld();
				}

				writer.WriteEndElement();
			}
		}

		/// <summary>
		/// Fills an unsorted list of categories.
		/// </summary>
		/// <returns>A List&lt;Category&gt; of all Categories.</returns>
		public List<Category> Fill()
		{
			string fileName = Provider.Folder + "categories.xml";
			if (!File.Exists(fileName))
				return null;

			XmlDocument doc = new XmlDocument();
			doc.Load(fileName);
			List<Category> categories = new List<Category>();

			foreach (XmlNode node in doc.SelectNodes("categories/category"))
			{
				Category category = new Category();

				category.Id = new Guid(node.Attributes["id"].InnerText);
				category.Title = node.InnerText;
				if (node.Attributes["description"] != null)
					category.Description = node.Attributes["description"].InnerText;
				if (node.Attributes["slug"] != null)
					category.Slug = node.Attributes["slug"].InnerText;
				if (node.Attributes["parent"] != null)
					category.Parent = new Guid(node.Attributes["parent"].InnerText);
				if (node.Attributes["order"] != null)
				{
					int myOrder = 0;
					int.TryParse(node.Attributes["order"].InnerText, out myOrder);
					category.Order = myOrder;
				}

				categories.Add(category);
				category.MarkOld();
			}

			return categories;
		}

	}
}
